<?php

/*
	This file is part of Mandragon.

    Mandragon is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Mandragon is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Mandragon.  If not, see <http://www.gnu.org/licenses/>.
*/
	
require_once 'PHPUnit/Framework.php';
require_once 'autoload.php';

class TestToolbox extends PHPUnit_Framework_TestCase {
	
	function test_util_set_ignored() {
		$menu = array('item1' => array('ignored' => false, 
									   'children' => array('item_a', 'item_b')),
					  'item_a' => array('ignored' => false,
										'children' => null),
					  'item_b' => array('ignored' => false,
										'children' => null),
					  'item2' => array('ignored' => false,
					  				   'children' => array('itemc', 'item_d')),
				      'item_c' => array('ignored' => false,
										'children' => null),
					  'item_d' => array('ignored' => false,
										'children' => null));
		$toolbox = new Toolbox();
		$actual = $toolbox->util_set_ignored('item1', $menu);

		$this->assertTrue($actual['item1']['ignored']);
		$this->assertTrue($actual['item_a']['ignored']);
		$this->assertTrue($actual['item_b']['ignored']);
		$this->assertFalse($actual['item2']['ignored']);
		$this->assertFalse($actual['item_c']['ignored']);
		$this->assertFalse($actual['item_d']['ignored']);
	}

	function test_fetch_moderators_with_no_dir_depth() {

		$toolbox = new Toolbox();

		$db_access = $this->getMock('DbAccessor');	
		$db_access->expects($this->never())
				  ->method('db_do_query');
		$db_access->expects($this->never())
				  ->method('db_query_select');
		$db_access->expects($this->never())
				  ->method('db_fetch_array');

		$toolbox->set_db_accessor($db_access);

		$page = new Page();
		$page->dir_depth = 0;

		$toolbox->fetch_moderators($page);
		$this->assertEquals(array(), $page->moderators);
	}

	function test_fetch_moderators_with_dir_depth() {

		$toolbox = new Toolbox();
		$dir_id = 3;

		$db_access = $this->getMock('DbAccessor');	
		$db_access->expects($this->once())
				  ->method('db_query_select')
				  ->with(array(array(), "MEMBER.nick"),
							   array("(ACCESS_RULE INNER JOIN IN_USERGROUP ON ACCESS_RULE.usergroup_id = IN_USERGROUP.usergroup_id) " .
									 "INNER JOIN MEMBER ON IN_USERGROUP.user_id = MEMBER.user_id", "DUMMY"), 
								 	 "action_id = 4 AND dir_id = $dir_id", "nick ASC")
				  ->will($this->returnValue("testOutputQuerySelect"));

		$db_access->expects($this->once())
				  ->method('db_do_query')
				  ->with("testOutputQuerySelect")
				  ->will($this->returnValue("testOutputSqlResult"));

		$expected_moderators = array(array('nick' => 'Frodo'),
									 array('nick' => 'Sam'));

		$db_access->expects($this->exactly(3))
				  ->method('db_fetch_array')
				  ->with("testOutputSqlResult")
				  ->will($this->onConsecutiveCalls($expected_moderators[0], 
				  								   $expected_moderators[1]));

		$toolbox->set_db_accessor($db_access);

		$page = new Page();
		$page->dir_depth = 1;
		$page->directory_tree[0]['dir_id'] = $dir_id;

		$toolbox->fetch_moderators($page);
		$this->assertEquals(array('Frodo', 'Sam'), $page->moderators);
	}

	function test_fetch_moderators_with_dir_depth_and_double_entries() {

		$toolbox = new Toolbox();
		$dir_id = 3;

		$db_access = $this->getMock('DbAccessor');	
		$db_access->expects($this->once())
				  ->method('db_query_select')
				  ->with(array(array(), "MEMBER.nick"),
							   array("(ACCESS_RULE INNER JOIN IN_USERGROUP ON ACCESS_RULE.usergroup_id = IN_USERGROUP.usergroup_id) " .
									 "INNER JOIN MEMBER ON IN_USERGROUP.user_id = MEMBER.user_id", "DUMMY"), 
								 	 "action_id = 4 AND dir_id = $dir_id", "nick ASC")
				  ->will($this->returnValue("testOutputQuerySelect"));

		$db_access->expects($this->once())
				  ->method('db_do_query')
				  ->with("testOutputQuerySelect")
				  ->will($this->returnValue("testOutputSqlResult"));

		$expected_moderators = array(array('nick' => 'Sam'),
									 array('nick' => 'Sam'));

		$db_access->expects($this->exactly(3))
				  ->method('db_fetch_array')
				  ->with("testOutputSqlResult")
				  ->will($this->onConsecutiveCalls($expected_moderators[0], 
				  								   $expected_moderators[1]));

		$toolbox->set_db_accessor($db_access);

		$page = new Page();
		$page->dir_depth = 1;
		$page->directory_tree[0]['dir_id'] = $dir_id;

		$toolbox->fetch_moderators($page);
		$this->assertEquals(array('Sam'), $page->moderators);
	}

	function test_get_micro_time() {
		$toolbox = new Toolbox();
		$actual = $toolbox->getmicrotime();

		//There isn't much that can be tested here.
		$this->assertGreaterThan(0, $actual);
	}

	function test_add_action() {
		$page = new Page();
		$id = 1385;
		$type = 'nonExistant';
		$action = 'doSomething';

		$toolbox = new Toolbox;
		$toolbox->add_action($page, $id, $type, $action);

		$actual = array_shift($page->actions);
		$this->assertEquals($id, $actual['id']);
		$this->assertEquals($type, $actual['type']);
		$this->assertEquals($action, $actual['action']);
		$this->assertEquals('', $actual['javascript']);
		$this->assertEquals(0, $actual['major']);
	}

	function test_add_action_url() {
		$page = new Page();
		$page->dir_path = "dirPath";
		$id = 1385;
		$type = 'url';
		$action = 'doSomething';

		$toolbox = new Toolbox();
		$toolbox->add_action($page, $id, $type, $action);

		$actual = array_shift($page->actions);
		$this->assertEquals($id, $actual['id']);
		$this->assertEquals($type, $actual['type']);
		$this->assertEquals("$page->dir_path/$action", $actual['action']);
		$this->assertEquals('', $actual['javascript']);
		$this->assertEquals(0, $actual['major']);
	}

	function test_add_action_url_action() {
		$page = new Page();
		$page->dir_path = "dirPath";
		$id = 1385;
		$type = 'url-action';
		$action = 'doSomething';

		$toolbox = new Toolbox();
		$toolbox->add_action($page, $id, $type, $action);

		$actual = array_shift($page->actions);
		$this->assertEquals($id, $actual['id']);
		$this->assertEquals($type, $actual['type']);
		$this->assertEquals("?action=$action", $actual['action']);
		$this->assertEquals('', $actual['javascript']);
		$this->assertEquals(0, $actual['major']);
	}

	function test_add_action_with_javascript() {
		$page = new Page();
		$id = 1385;
		$type = 'nonExistant';
		$action = 'doSomething';
		$expected_javascript = 'alert("hackerdehack")';

		$toolbox = new Toolbox();
		$toolbox->add_action($page, $id, $type, $action, $expected_javascript);

		$actual = array_shift($page->actions);
		$this->assertEquals($id, $actual['id']);
		$this->assertEquals($type, $actual['type']);
		$this->assertEquals($action, $actual['action']);
		$this->assertEquals($expected_javascript, $actual['javascript']);
		$this->assertEquals(0, $actual['major']);
	}

	function test_add_action_with_major_action() {
		$page = new Page();
		$id = 1385;
		$type = 'nonExistant';
		$action = 'doSomething';
		$expected_major_action = 1;

		$toolbox = new Toolbox();
		$toolbox->add_action($page, $id, $type, $action, '', $expected_major_action);

		$actual = array_shift($page->actions);
		$this->assertEquals($id, $actual['id']);
		$this->assertEquals($type, $actual['type']);
		$this->assertEquals($action, $actual['action']);
		$this->assertEquals('', $actual['javascript']);
		$this->assertEquals($expected_major_action, $actual['major']);
	}

	function test_get_keys_and_values() {
		$expected_key_field_name = "key";
		$expected_value_field_name = "value";
		$expected_table = "table";
		$expected_sql_result = 'generated_sql_query';
		$expected_result = 'db_output';
		$expected_key = 'expectedKey';
		$expected_value = 'expectedValue';

		$expected_array_result = array($expected_key_field_name => $expected_key,
									   $expected_value_field_name => $expected_value);
		
		$toolbox = new Toolbox();
		
		$mock_db_access = $this->getMock("DbAccessor");
		$mock_db_access->expects($this->once())
					   ->method('db_query_select')
					   ->with(array(array($expected_key_field_name, $expected_value_field_name)), array($expected_table), 1, '')
					   ->will($this->returnValue($expected_sql_result));
		$mock_db_access->expects($this->once())
					   ->method('db_do_query')
					   ->with($expected_sql_result)
					   ->will($this->returnValue($expected_result));
		$mock_db_access->expects($this->exactly(2))
					   ->method('db_fetch_array')
					   ->with($expected_result)
					   ->will($this->onConsecutiveCalls($expected_array_result, null));
		$toolbox->set_db_accessor($mock_db_access);

		$actual = $toolbox->get_keys_and_values($expected_key_field_name, $expected_value_field_name, $expected_table);
		$this->assertEquals(array($expected_key), $actual['keys']);
		$this->assertEquals(array($expected_value), $actual['values']);
	}

	function test_get_keys_and_values_with_where_and_order() {
		$expected_key_field_name = "key";
		$expected_value_field_name = "value";
		$expected_table = "table";
		$expected_sql_result = 'generated_sql_query';
		$expected_result = 'db_output';
		$expected_key = 'expectedKey';
		$expected_value = 'expectedValue';
		$expected_where = 'where';
		$expected_order = 'order';

		$expected_array_result = array($expected_key_field_name => $expected_key,
									   $expected_value_field_name => $expected_value);
		
		$toolbox = new Toolbox();
		
		$mock_db_access = $this->getMock("DbAccessor");
		$mock_db_access->expects($this->once())
					   ->method('db_query_select')
					   ->with(array(array($expected_key_field_name, $expected_value_field_name)), array($expected_table), 
					   			$expected_where, $expected_order)
					   ->will($this->returnValue($expected_sql_result));
		$mock_db_access->expects($this->once())
					   ->method('db_do_query')
					   ->with($expected_sql_result)
					   ->will($this->returnValue($expected_result));
		$mock_db_access->expects($this->exactly(2))
					   ->method('db_fetch_array')
					   ->with($expected_result)
					   ->will($this->onConsecutiveCalls($expected_array_result, null));
		$toolbox->set_db_accessor($mock_db_access);

		$actual = $toolbox->get_keys_and_values($expected_key_field_name, $expected_value_field_name, $expected_table,
				$expected_where, $expected_order);

		$this->assertEquals(array($expected_key), $actual['keys']);
		$this->assertEquals(array($expected_value), $actual['values']);
	}

	function test_get_keyed_values() {
	
		$expected_sql_query = "generated_sql_query";
		$expected_sql_result = "sql_result";
		$expected_key_field_name = "key";
		$expected_value_field_name = "value";
		$expected_key_result = 'key_result';
		$expected_value_result = 'value_result';
		$expected_table = 'table';

		$expected_array_result = array($expected_key_field_name => $expected_key_result, 
									   $expected_value_field_name => $expected_value_result);

		$toolbox = new Toolbox();

		$mock_db_access = $this->getMock('DbAccessor');
		$mock_db_access->expects($this->once())
					   ->method('db_query_select')
					   ->with(array(array($expected_key_field_name, $expected_value_field_name)), 
					   			array($expected_table), 1, '')
					   ->will($this->returnValue($expected_sql_query));
		$mock_db_access->expects($this->once())
					   ->method('db_do_query')
					   ->with($expected_sql_query)
					   ->will($this->returnValue($expected_sql_result));
		$mock_db_access->expects($this->exactly(2))
					   ->method('db_fetch_array')
					   ->with($expected_sql_result)
					   ->will($this->onConsecutiveCalls($expected_array_result, null));
		$toolbox->set_db_accessor($mock_db_access);
		
		$actual = $toolbox->get_keyed_values($expected_key_field_name, $expected_value_field_name, $expected_table);
		$this->assertEquals($expected_value_result, $actual[$expected_key_result]);
	}

	function test_add_log() {
		
		$expected_sqlize_input = $_SERVER["REMOTE_ADDR"]." - ".$_SERVER["HTTP_X_FORWARDED_FOR"];
		$expected_string = 'inputstring';
		$expected_first_call = 'first_call';
		$expected_second_call = 'second_call';
		$expected_insert_input1 = array('log_date', 'log', 'ipstring');
		$expected_insert_input2 = array('NOW(14)', $expected_first_call, $expected_second_call);
		$expected_insert_input3 = 'LOG';
		$expected_query_output = 'insert_query_output';
		$expected_final_output = 'final_output';

		$toolbox = new Toolbox();

		$mock_db_access = $this->getMock('DbAccessor');
		$mock_db_access->expects($this->at(0))
					   ->method('db_sqlize')
					   ->with($expected_string)
					   ->will($this->returnValue($expected_first_call));
		$mock_db_access->expects($this->at(1))
					   ->method('db_sqlize')
					   ->with($expected_sqlize_input)
					   ->will($this->returnValue($expected_second_call));
		$mock_db_access->expects($this->once())
						->method('db_query_insert')
						->with($expected_insert_input1, $expected_insert_input2, $expected_insert_input3)
						->will($this->returnValue($expected_query_output));
		$mock_db_access->expects($this->once())
						->method('db_do_query')
						->with($expected_query_output)
						->will($this->returnValue($expected_final_output));
		$toolbox->set_db_accessor($mock_db_access);

		$toolbox->add_log($expected_string);
	}

	function test_end_page() {
		$this->markTestIncomplete("Involves skin. Find some way to test this.");
	}

	function test_get_last_clicks_with_no_records() {

		$expected_session_user = 'session user';
		$_SESSION['user_id'] = $expected_session_user;

		$expected_input = 'expected input';
		$expected_sql_select1 = array(array("user_id", "nick"));
		$expected_sql_select2 = array("MEMBER"); 
		$expected_sql_select3 = "user_id != $expected_session_user AND (DATE_ADD(last_click, INTERVAL 10 MINUTE) > NOW(14))";
		$expected_sql_select4 = "nick ASC";
		$expected_nr_records = 5;

		$toolbox = new Toolbox();

		$mock_db_access = $this->getMock('DbAccessor');
		$mock_db_access->expects($this->once())
						->method('db_query_select')
						->with($expected_sql_select1, $expected_sql_select2, 
								$expected_sql_select3, $expected_sql_select4)
						->will($this->returnValue($expected_input));
		$mock_db_access->expects($this->once())
						->method('db_do_query')
						->with($expected_input)
						->will($this->returnValue($expected_nr_records));
		$mock_db_access->expects($this->once())
						->method('db_num_rows')
						->with($expected_nr_records)
						->will($this->returnValue(0));

		$toolbox->set_db_accessor($mock_db_access);

		$actual = $toolbox->get_last_clicks();
		$this->assertEquals(array(), $actual);
	}

	function test_get_last_clicks_with_records() {

		$expected_session_user = 'session user';
		$_SESSION['user_id'] = $expected_session_user;

		$expected_name = 'Jef';
		$expected_input = 'expected input';
		$expected_sql_select1 = array(array("user_id", "nick"));
		$expected_sql_select2 = array("MEMBER"); 
		$expected_sql_select3 = "user_id != $expected_session_user AND (DATE_ADD(last_click, INTERVAL 10 MINUTE) > NOW(14))";
		$expected_sql_select4 = "nick ASC";
		$expected_nr_records = 5;

		$toolbox = new Toolbox();

		$mock_db_access = $this->getMock('DbAccessor');
		$mock_db_access->expects($this->once())
						->method('db_query_select')
						->with($expected_sql_select1, $expected_sql_select2, 
								$expected_sql_select3, $expected_sql_select4)
						->will($this->returnValue($expected_input));
		$mock_db_access->expects($this->once())
						->method('db_do_query')
						->with($expected_input)
						->will($this->returnValue($expected_nr_records));
		$mock_db_access->expects($this->once())
						->method('db_num_rows')
						->with($expected_nr_records)
						->will($this->returnValue(1));
		$mock_db_access->expects($this->exactly(2))
						->method('db_fetch_array')
						->with($expected_nr_records)
						->will($this->onConsecutiveCalls($expected_name, null));

		$toolbox->set_db_accessor($mock_db_access);

		$actual = $toolbox->get_last_clicks();
		$this->assertEquals(array($expected_name), $actual);
	}

	function test_click() {
		$expected_session_user = 'session user';
		$_SESSION['user_id'] = $expected_session_user;

		$expected_sql_select1 = array('member_since', 'last_visit', 'last_click'); 
		$expected_sql_select2 = array('member_since', 'last_visit', 'NOW(14)'); 
		$expected_sql_select3 = "MEMBER"; 
		$expected_sql_select4 = "user_id = $expected_session_user";
		$expected_sql_output = 'sql_output';

		$toolbox = new Toolbox();
		$mock_db_access = $this->getMock('DbAccessor');
		$mock_db_access->expects($this->once())
						->method('db_query_update')
						->with($expected_sql_select1, $expected_sql_select2,
								$expected_sql_select3, $expected_sql_select4)
						->will($this->returnValue($expected_sql_output));

		$mock_db_access->expects($this->once())
						->method('db_do_query')
						->with($expected_sql_output);
		$toolbox->set_db_accessor($mock_db_access);

		$toolbox->click();

	}
}

?>
